home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Mail / Sources / UMailingApplication.cp < prev   
Encoding:
Text File  |  1996-04-03  |  13.3 KB  |  421 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UMailingApplication.cp 
  3. // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #if qPowerTalk
  7.  
  8. #ifndef __UMAILINGAPPLICATION__
  9. #include "UMailingApplication.h"
  10. #endif
  11.  
  12. // MacApp
  13.  
  14. #ifndef __UDOCUMENT__
  15. #include "UDocument.h"
  16. #endif
  17.  
  18. #ifndef __UERRORMGR__
  19. #include "UErrorMgr.h"
  20. #endif
  21.  
  22. #ifndef __UFILE__
  23. #include "UFile.h"
  24. #endif
  25.  
  26. #ifndef __UMACAPPGLOBALS__
  27. #include "UMacAppGlobals.h"
  28. #endif
  29.     
  30. #ifndef __UMACAPPUTILITIES__
  31. #include "UMacAppUtilities.h"
  32. #endif
  33.     
  34. #ifndef __UMEMORY__
  35. #include "UMemory.h"
  36. #endif
  37.  
  38. #ifndef __UMENUMGR__
  39. #include "UMenuMgr.h"
  40. #endif
  41.  
  42. // Toolbox
  43.  
  44. #ifndef __AEREGISTRY__
  45. #include <AERegistry.h>
  46. #endif
  47.  
  48. // ANSI
  49.  
  50. #ifndef __STDIO__
  51. #include <stdio.h>
  52. #endif
  53.  
  54. //========================================================================================
  55. // LOCAL variables
  56. //========================================================================================
  57.  
  58. static AECoercionHandlerUPP pTextToDSSpecUPP;
  59. static AECoercionHandlerUPP pDSSpecToTextUPP;
  60.  
  61. //========================================================================================
  62. // CLASS TMailingApplication
  63. //========================================================================================
  64. #undef Inherited
  65.  
  66. #pragma segment MAOpen
  67. #define Inherited TApplication
  68.  
  69. MA_DEFINE_CLASS_M2(TMailingApplication, Inherited, MMailing);
  70.  
  71. //----------------------------------------------------------------------------------------
  72. // TMailingApplication constructor
  73. //----------------------------------------------------------------------------------------
  74. #pragma segment MAOpen
  75.  
  76. TMailingApplication::TMailingApplication()
  77. {
  78.     fMainLetterFileType = kStandardLetterFileType;
  79. }
  80.  
  81. //----------------------------------------------------------------------------------------
  82. // TMailingApplication destructor
  83. //----------------------------------------------------------------------------------------
  84. #pragma segment MAOpen
  85.  
  86. TMailingApplication::~TMailingApplication()
  87. {
  88.     pTextToDSSpecUPP = DisposeIfRoutineDescriptor(pTextToDSSpecUPP);
  89.     pDSSpecToTextUPP = DisposeIfRoutineDescriptor(pDSSpecToTextUPP);
  90. }
  91.  
  92. //----------------------------------------------------------------------------------------
  93. // TMailingApplication::IMailingApplication: 
  94. //----------------------------------------------------------------------------------------
  95. #pragma segment MAInit
  96.  
  97. void TMailingApplication::IMailingApplication(OSType itsMainFileType,
  98.                                               OSType itsMailType,
  99.                                               OSType itsCreator)
  100. {
  101.     IApplication(itsMainFileType, itsCreator);
  102.     
  103.     fMainLetterFileType = itsMailType;
  104.     
  105.     // Install AE Coercion handlers
  106.     AECoercionHandlerUPP handler = NULL;
  107.     long handlerRefcon = 0;
  108.     Boolean fromTypeIsDesc;
  109.     Boolean isSysHandler = FALSE;
  110.     if (AEGetCoercionHandler(typeChar, typePackedDSSpec, &handler, &handlerRefcon, &fromTypeIsDesc, isSysHandler) == errAEHandlerNotFound)
  111.     {
  112.         if (!pTextToDSSpecUPP)
  113.             pTextToDSSpecUPP = (AECoercionHandlerUPP) NewAECoercePtrProc(TextToDSSpecGlue);
  114.         
  115.         FailOSErr(AEInstallCoercionHandler(typeChar, typePackedDSSpec, pTextToDSSpecUPP, 0, FALSE, FALSE));
  116.     }
  117.     
  118.     if (AEGetCoercionHandler(typePackedDSSpec, typeChar, &handler, &handlerRefcon, &fromTypeIsDesc, isSysHandler) == errAEHandlerNotFound)
  119.     {
  120.         if (!pDSSpecToTextUPP)
  121.             pDSSpecToTextUPP = (AECoercionHandlerUPP) NewAECoercePtrProc(DSSpecToTextGlue);
  122.         
  123.         FailOSErr(AEInstallCoercionHandler(typePackedDSSpec, typeChar, pDSSpecToTextUPP, 0, FALSE, FALSE));
  124.     }
  125. }
  126.  
  127. //----------------------------------------------------------------------------------------
  128. // TMailingApplication::DoMenuCommand: 
  129. //----------------------------------------------------------------------------------------
  130. #pragma segment MASelCommand
  131.  
  132. void TMailingApplication::DoMenuCommand(CommandNumber aCommandNumber)
  133. {
  134.     if (aCommandNumber == cOpenNextLetter)
  135.         this->DoOpenNextLetter(aCommandNumber);
  136.     else
  137.         Inherited::DoMenuCommand(aCommandNumber);
  138. }
  139.  
  140. //----------------------------------------------------------------------------------------
  141. // TMailingApplication::DoSetupMenus: 
  142. //----------------------------------------------------------------------------------------
  143. #pragma segment MAApplicationRes
  144.  
  145. void TMailingApplication::DoSetupMenus()
  146. {
  147.     Inherited::DoSetupMenus();
  148.     Enable(cOpenNextLetter, HasAOCEToolBox());
  149.     
  150.     // We don't want the menu to say "Remove Mailer" if there aren't any documents.
  151.     if (!fDocumentList || fDocumentList->GetSize() <= 0)
  152.         SetIndividualCommandName(cAddMailer, kAOCEStrings, kAddMailerCmdName);
  153. }
  154.  
  155. //----------------------------------------------------------------------------------------
  156. // TMailingApplication::DoToolboxEvent: 
  157. //----------------------------------------------------------------------------------------
  158. #pragma segment MAApplicationRes
  159.  
  160. void TMailingApplication::DoToolboxEvent(TToolboxEvent* event)
  161. {
  162.     if (!this->DoMailerEvent(event))
  163.         Inherited::DoToolboxEvent(event);
  164. }
  165.  
  166. //----------------------------------------------------------------------------------------
  167. // TMailingApplication::Idle: 
  168. //----------------------------------------------------------------------------------------
  169. #pragma segment MAApplicationRes
  170.  
  171. void TMailingApplication::Idle(IdlePhase phase)
  172. {
  173.     // Give the mail package some idle time
  174.     DoMailerEvent(NULL);
  175.     Inherited::Idle(phase);
  176. }
  177.  
  178. //----------------------------------------------------------------------------------------
  179. // TMailingApplication::OpenOld: 
  180. //----------------------------------------------------------------------------------------
  181. #pragma segment MAOpen
  182.  
  183. TDocument* TMailingApplication::OpenOld(CommandNumber itsOpenCommand, TList* aFileList)
  184. {
  185.     MAVolatileInit(TDocument*, aDocument, NULL);
  186.     MAVolatileInit(TFile*, aFile, NULL);
  187.     MAVolatileInit(TFile*, aNewFile, NULL);
  188.     
  189.     MAVolatileInit(OSErr, savedError, 0);
  190.     MAVolatileInit(long, savedMessage, 0);
  191.     
  192.     Size    oldCodeReserve;
  193.     Size    oldMemReserve;
  194.     
  195.     GetReserveSize(oldCodeReserve, oldMemReserve);
  196.     
  197.   {
  198.       // Put iterator in a separate block so that it will go out of scope before the end of the method.
  199.     // We don't want the iterator's failure handler to be invoked, because its stack ptr is munged.
  200.     // If an error occurs, we'll just save it and ReSignal it after the iterator is gone.
  201.  
  202.     CObjectIterator iter(aFileList);
  203.     for (aFile = (TFile *)iter.FirstObject(); iter.More() && !savedError; aFile = (TFile *)iter.NextObject())
  204.     {
  205.         CommandNumber kindOfDocCmd = this->KindOfDocument(itsOpenCommand, aFile);
  206.         // reset aDocument and aNewFile so that they no longer refer to items from the
  207.         // last go round (important in case we fail downstream)…
  208.         aDocument = NULL;
  209.         aNewFile = NULL;
  210.         
  211.         CStr63 fileName;
  212.         aFile->GetName(fileName);            // If failure occurs the file may already be
  213.                                             // freed so we will save the name just in
  214.                                             // case.
  215.         
  216.         aFileList->Delete(aFile);            // ReadStationery if successful will dispose
  217.                                             // of the file for us so if failure occurs
  218.                                             // this had better not be in the file list.
  219.         
  220.         FailInfo fi;
  221.         Try(fi)
  222.         {
  223.             // Set reserve down a little to ensure that we can open existing documents 
  224.             SetReserveSize(oldCodeReserve, oldMemReserve / 2);
  225.             
  226.             TDocument * otherDoc = this->FindDocument(aFile);
  227.             Boolean isStationery = aFile->IsStationery();
  228.  
  229.             if (otherDoc && !isStationery)
  230.             {
  231.                 otherDoc->OpenAgain(kindOfDocCmd, aDocument);
  232.                 aFile = (TFile*)FreeIfObject(aFile);
  233.                 SetReserveSize(oldCodeReserve, oldMemReserve);
  234.             }
  235.             else if (this->CanOpenDocument(kindOfDocCmd, aFile))
  236.             {
  237.                 TFile* fileOwnedByDoc = aFile;
  238.                 aFile = NULL;
  239.                 AuthIdentity localIdentity;
  240.                 
  241.                 Boolean isLetter = IsLetterFileType(fileOwnedByDoc->fFileType);
  242.                 if (!isLetter || gMailing->GetAOCEIdentity(localIdentity, TRUE) == noErr)
  243.                 {
  244.                     FailNIL(aDocument = this->DoMakeDocument(kindOfDocCmd, fileOwnedByDoc));
  245.     
  246.                     if (isLetter)
  247.                     {
  248.                         MMailable* mailDoc = MA_DYNAMIC_CAST(MMailable, aDocument);
  249.                         if (mailDoc)
  250.                             mailDoc->ReadLetter(kForDisplay);
  251.                     }
  252.                     else
  253.                     if (!isStationery)
  254.                         aDocument->ReadDocument(kForDisplay);
  255.                     else
  256.                     {
  257.                         aNewFile = this->DoMakeFile(kindOfDocCmd);
  258.                         aDocument->ReadStationery(aNewFile);
  259.                         aFile = NULL;                // This file has already been freed by ReadStationery.
  260.                         aNewFile = NULL;            // Clear our reference so that if we fail
  261.                                                     // we don't try to free this file twice.
  262.                     }
  263.                     
  264.                     aDocument->DoMakeViews(kForDisplay);
  265.     
  266.                     if (isLetter)
  267.                     {
  268.                         MMailable* mailDoc = MA_DYNAMIC_CAST(MMailable, aDocument);
  269.                         if (mailDoc)
  270.                             mailDoc->OpenLetter();
  271.                     }
  272.                         
  273.                     if (isStationery)
  274.                     {
  275.                         CStr255 newTitle;
  276.                         aDocument->UntitledName(newTitle);
  277.                         aDocument->SetTitle(newTitle);
  278.                     }
  279.         
  280.                     FailSpaceIsLow();                // Fail if the document leaves us with no
  281.                                                     // memory
  282.                     // Set the reserve back to where it was 
  283.                     SetReserveSize(oldCodeReserve, oldMemReserve);
  284.         
  285.                     // Don't attempt to show the windows until we're sure we won't fail 
  286.                     aDocument->DoPostMakeViews(kForDisplay);
  287.                 }
  288.             }
  289.             else
  290.                 Failure(errNotMyType, 0);
  291.             fi.Success();
  292.         }
  293.         else // Recover
  294.         {
  295.             if (fi.message == 0)
  296.                 gErrorParm3 = fileName;
  297.                 
  298.             // We may have ended up without a document because of a failure during document init.
  299.             // b/c this can be the case we don't know what happened to aFile, whether it was freed
  300.             // by the document in the failure process or orphaned. Because of this we will not free
  301.             // aFile here.
  302.             if (aDocument)
  303.                 aDocument = (TDocument *)(FreeIfObject(aDocument));    // The document will free the file
  304.                 
  305.             aNewFile = (TFile*)FreeIfObject(aNewFile);                // If we successfully read the
  306.                                                                     // stationery then aNewFile will be NULL
  307.             
  308.             // Set the reserve back to where it was 
  309.             SetReserveSize(oldCodeReserve, oldMemReserve);
  310.             
  311.             //    Don't want to fail here, because the CObjectIterator (with its embedded FailInfo) is 
  312.             //    still in scope. Instead, save the error info until after the iterator has self-destructed.
  313.             //    FailNewMessage(fi.error, fi.message, messageOpenFailed);
  314.             savedError = fi.error;
  315.             savedMessage = fi.message;
  316.             if (!savedMessage)
  317.                 savedMessage = messageOpenFailed;
  318.         }
  319.     }
  320.   } // iterator will self-destruct now
  321.  
  322.       if (savedError != noErr)                        // Do we need to ReSignal a failure?
  323.     {
  324.         // signal the failure
  325.         Failure(savedError, savedMessage);
  326.     }
  327.     return aDocument;
  328. }
  329.  
  330. //----------------------------------------------------------------------------------------
  331. // TMailingApplication::GetFileTypeList: 
  332. //----------------------------------------------------------------------------------------
  333. #pragma segment MAOpen
  334.  
  335. void TMailingApplication::GetFileTypeList(CommandNumber itsCommandNumber,
  336.                                    TypeListHandle& typeList)
  337. {
  338.     if (HasAOCEToolBox())
  339.     {
  340.         typeList = (TypeListHandle) NewPermHandle(8);
  341.         (*typeList)[0] = fMainFileType;
  342.         (*typeList)[1] = fMainLetterFileType;
  343.     }
  344.     else
  345.         Inherited::GetFileTypeList(itsCommandNumber, typeList);
  346. }
  347.  
  348. //----------------------------------------------------------------------------------------
  349. // TMailingApplication::DoAECreateElement: 
  350. //----------------------------------------------------------------------------------------
  351. #pragma segment MAScriptingRes
  352.  
  353. void TMailingApplication::DoAECreateElement(TAppleEvent* message,
  354.                                             TAppleEvent* reply)
  355. {
  356.     DescType theClass = message->ReadType(keyAEObjectClass);
  357.     if (theClass == cReplyDocument)
  358.     {
  359.         AuthIdentity localIdentity;    
  360.                                 
  361.         if (CommandEnabled(cNew) && (gMailing->GetAOCEIdentity(localIdentity, TRUE) == noErr))
  362.         {
  363.             TDocument * theDoc = this->OpenNew(cNew);
  364.             theDoc->SetPropertiesFromEvent(message);    // Apply the properties if any.
  365.  
  366.             if (message->HasParameter(keyAEData))
  367.             {
  368.                 if (theClass == cReplyDocument && HasAOCEToolBox())
  369.                 {
  370.                     MMailable* mailDoc = MA_DYNAMIC_CAST(MMailable, theDoc);
  371.                     if (mailDoc)
  372.                         mailDoc->DoAECreateReply(message, reply);
  373.                 }
  374.                 else
  375.                     theDoc->DoAESetData(message, reply);
  376.             }
  377.  
  378.             // Return the document's object specifier
  379.             CTempDesc theDocsSpecifier;
  380.             theDoc->MakeObjectSpecifier(theDocsSpecifier, formName);
  381.             if (reply->fMessage.dataHandle)
  382.                 reply->WriteParameter(keyAEResult, theDocsSpecifier);
  383.         }
  384.     }
  385.     else
  386.         Inherited::DoAECreateElement(message, reply);
  387. }
  388.  
  389. //----------------------------------------------------------------------------------------
  390. // TMailingApplication::DoScriptCommand: 
  391. //----------------------------------------------------------------------------------------
  392. #pragma segment MAScriptingRes
  393.  
  394. void TMailingApplication::DoScriptCommand(CommandNumber    aCommandNumber,
  395.                                             TAppleEvent*     message,
  396.                                                TAppleEvent*     reply)
  397. {
  398.     switch (aCommandNumber)
  399.     {
  400.         case cAEOpenNextLetter:
  401.             if (HasAOCEToolBox())
  402.             {
  403.                 TOpenNextLetterCommand* anOpenNextLetterCommand = new TOpenNextLetterCommand;
  404.                 anOpenNextLetterCommand->IOpenNextLetterCommand(aCommandNumber);
  405.                 anOpenNextLetterCommand->Process();
  406.             }
  407.             break;
  408.  
  409.         default:
  410.             Inherited::DoScriptCommand(aCommandNumber, message, reply);
  411.             break;
  412.     }
  413. }
  414.  
  415. #endif // qPowerTalk
  416.  
  417. //----------------------------------------------------------------------------------------
  418. // End of UMailingApplication.cp
  419.  
  420. #pragma segment Inline
  421.